<!---
	Define function that will recursively search a
	struct and it's nested elements for keys that should
	be considered secure and blacked out.
--->
<cffunction
	name="MakeStructSecure"
	access="public"
	returntype="any"
	output="false"
	hint="Does a very cursory job of cleaning up a struct by blacking out secure information.">
 
	<!--- Define argumets. --->
	<cfargument
		name="Struct"
		type="struct"
		required="true"
		hint="The struct we are going to clean."
		/>
 
	<cfargument
		name="Depth"
		type="numeric"
		required="false"
		default="1"
		hint="The depth of the current search - this will stop the function from looping infinitely."
		/>
 
	<!--- Define the local scope. --->
	<cfset var LOCAL = StructNew() />
 
	<!---
		Check to see if we have reached our max depth
		for this search.
	--->
	<cfif (ARGUMENTS.Depth GTE 5)>
 
		<!---
			You're going too deep, it hurts! We might be
			looping in a circular struct reference.
		--->
		<cfreturn />
 
	</cfif>
 
 
	<!---
		ASSERT: If we have made it this far, then we have
		to check all the struct keys at this level.
	--->
 
	<!---
		Define the list of keys that would be considered
		to hold secure data.
	--->
	<cfsavecontent variable="LOCAL.SecureKeys">
		CreditCard
		CCNumber
		CCNum
		ExpirationDate
		Expry
		ExpDate
		CCExp
		passcode
		password
	</cfsavecontent>
 
 
	<!---
		Loop over the struct looking for keys that would
		flag secure data to be removed.
	--->
	<cfloop
		item="LOCAL.Key"
		collection="#ARGUMENTS.Struct#">
 
		<!---
			Check to see if the key is to be considered
			secure AND that the value in it is simple.
		--->
		<cfif (
			FindNoCase( LOCAL.Key, LOCAL.SecureKeys ) AND
			IsSimpleValue( ARGUMENTS.Struct[ LOCAL.Key ] )
			)>
 
			<!--- Black out value. --->
			<cfset ARGUMENTS.Struct[ LOCAL.Key ] = RepeatString(
				"*",
				Len( ARGUMENTS.Struct[ LOCAL.Key ] )
				) />
 
		<!---
			Check to see if this key is a struct that we
			might have to search through.
		--->
		<cfelseif IsStruct( ARGUMENTS.Struct[ LOCAL.Key ] )>
 
			<!---
				Recurse through this one. Be sure to send
				through a new depth value so we don't loop
				forever.
			--->
			<cfset MakeStructSecure(
				Struct = ARGUMENTS.Struct[ LOCAL.Key ],
				Depth = (ARGUMENTS.Depth + 1)
				) />
 
		</cfif>
 
	</cfloop>
 
 
	<!--- Return out. --->
	<cfif (ARGUMENTS.Depth EQ 1)>
 
		<!--- Return the cleaned struct. --->
		<cfreturn ARGUMENTS.Struct />
 
	<cfelse>
		<cfreturn />
	</cfif>
</cffunction>